home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Moscow ML 1.42 / src / mosmllib / BasicIO.sml < prev    next >
Encoding:
Text File  |  1997-08-18  |  7.7 KB  |  248 lines  |  [TEXT/R*ch]

  1. (* BasicIO.sml *)
  2.  
  3. prim_val create_string_ : int -> string = 1 "create_string";
  4. prim_val nth_char_ : string -> int -> char = 2 "get_nth_char";
  5. prim_val set_nth_char_ : string -> int -> char -> unit = 3 "set_nth_char";
  6. prim_val blit_string_ :
  7.   string -> int -> string -> int -> int -> unit = 5 "blit_string";
  8.  
  9. fun sub_string_ s start len =
  10.   let val res = create_string_ len
  11.   in blit_string_ s start res 0 len; res end
  12. ;
  13.  
  14. (* Caml Light "channels" *)
  15.  
  16. prim_type in_channel and out_channel;
  17.  
  18. prim_val open_descriptor_in : int -> in_channel = 1 "open_descriptor";
  19.         (* [open_descriptor_in fd] returns a buffered input channel
  20.            reading from the file descriptor [fd]. The file descriptor [fd]
  21.            must have been previously opened for reading, else the behavior is
  22.        undefined. *)
  23.  
  24. prim_val open_descriptor_out : int -> out_channel = 1 "open_descriptor";
  25.         (* [open_descriptor_out fd] returns a buffered output channel
  26.            writing to the file descriptor [fd]. The file descriptor [fd]
  27.            must have been previously opened for writing, else the behavior is
  28.        undefined. *)
  29.  
  30. prim_val input_char_ : in_channel -> char = 1 "input_char"
  31.         (* Read one character from the given input channel.
  32.            Raise [Size] if there are no more characters to read. *)
  33.  
  34. prim_val caml_seek_in : in_channel -> int -> unit = 2 "seek_in"
  35.         (* [seek_in chan pos] sets the current reading position to [pos]
  36.            for channel [chan]. *)
  37.  
  38. prim_val caml_pos_in : in_channel -> int = 1 "pos_in";
  39.         (* Return the current reading position for the given channel. *)
  40.  
  41. prim_val caml_close_in : in_channel -> unit = 1 "close_in"
  42.         (* Close the given channel. Anything can happen if any of the
  43.            above functions is called on a closed channel. *)
  44.  
  45. type file_perm = int;
  46.  
  47. datatype open_flag =
  48.     O_RDONLY                       (* `open' read-only *)
  49.   | O_WRONLY                       (* `open' write-only *)
  50.   | O_RDWR                         (* `open' for reading and writing *)
  51.   | O_APPEND                       (* `open' for appending *)
  52.   | O_CREAT                        (* create the file if nonexistent *)
  53.   | O_TRUNC                        (* truncate the file to 0 if it exists *)
  54.   | O_EXCL                         (* fails if the file exists *)
  55.   | O_BINARY                       (* `open' in binary mode *)
  56.   | O_TEXT                         (* `open' in text mode *)
  57. ;
  58.  
  59. prim_val sys_open :
  60.   string -> open_flag list -> file_perm -> int = 3 "sys_open"
  61.         (* Open a file. The second argument is the opening mode.
  62.            The third argument is the permissions to use if the file
  63.            must be created. The result is a file descriptor opened on the
  64.            file. *)
  65. prim_val sys_close :
  66.   int -> unit = 1 "sys_close"
  67.         (* Close a file descriptor. *)
  68.  
  69. val caml_std_in  = open_descriptor_in 0
  70. and caml_std_out = open_descriptor_out 1
  71. and caml_std_err = open_descriptor_out 2
  72. ;
  73.  
  74. (* Moscow ML streams *)
  75.  
  76. type instream  = { closed: bool, ic: in_channel } ref;
  77. type outstream = { closed: bool, oc: out_channel } ref;
  78.  
  79. val std_in  : instream  = ref { closed=false, ic=caml_std_in }
  80. and std_out : outstream = ref { closed=false, oc=caml_std_out }
  81. and std_err : outstream = ref { closed=false, oc=caml_std_err }
  82. ;
  83.  
  84. prim_val fast_input :
  85.   in_channel -> string -> int -> int -> int = 4 "input";
  86. prim_val fast_output :
  87.   out_channel -> string -> int -> int -> unit = 4 "output";
  88.  
  89. fun caml_open_in_gen mode rights filename =
  90.   open_descriptor_in (sys_open filename mode rights)
  91. ;
  92.  
  93. val caml_open_in = caml_open_in_gen [O_RDONLY, O_TEXT] 0
  94. and caml_open_in_bin = caml_open_in_gen [O_RDONLY, O_BINARY] 0
  95. ;
  96.  
  97. fun open_out_gen mode rights filename =
  98.   open_descriptor_out(sys_open filename mode rights)
  99. ;
  100.  
  101. prim_val s_irall : file_perm = 0 "s_irall";
  102. prim_val s_iwall : file_perm = 0 "s_iwall";
  103.  
  104. val caml_open_out =
  105.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_TEXT] (s_irall + s_iwall)
  106. and caml_open_out_bin =
  107.   open_out_gen [O_WRONLY, O_TRUNC, O_CREAT, O_BINARY] (s_irall + s_iwall)
  108. ;
  109.  
  110. prim_val caml_flush : out_channel -> unit = 1 "flush"
  111.         (* Flush the buffer associated with the given output channel,
  112.            performing all pending writes on that channel.
  113.            Interactive programs must be careful about flushing [std_out]
  114.            at the right times. *)
  115.  
  116. fun caml_output_string channel s =
  117.   fast_output channel s 0 (size s)
  118. ;
  119.  
  120. prim_val caml_close_out : out_channel -> unit = 1 "close_out"
  121.         (* Close the given channel, flushing all buffered write operations.
  122.        The behavior is unspecified if any of the above functions is
  123.        called on a closed channel. *)
  124.  
  125. fun raiseIo fcn nam exn = 
  126.     raise SysErr ("BasicIO." ^ fcn ^ " on " ^ nam, NONE);
  127.  
  128. fun raiseClosed fcn nam = 
  129.     raiseIo fcn nam (Fail "Stream is closed");
  130.  
  131. fun open_in s =
  132.   ref {closed=false, ic=caml_open_in s}
  133.   handle exn as SysErr _ => raiseIo "open_in" s exn;
  134.  
  135. fun open_in_bin s =
  136.   ref {closed=false, ic=caml_open_in_bin s}
  137.   handle exn as SysErr _ => raiseIo "open_in_bin" s exn;
  138.  
  139. fun try_input_char_ ic =
  140.   SOME (input_char_ ic)
  141.   handle Size => NONE;
  142.  
  143. fun inputc (is as ref {closed, ic}) n =
  144.   if closed orelse n<=0 then "" else
  145.   let
  146.     val buff = create_string_ n
  147.     fun loop k =
  148.       if k = n then buff
  149.       else
  150.         case fast_input ic buff k (n-k) of
  151.             0 => sub_string_ buff 0 k
  152.           | m => loop (k+m)
  153.   in loop 0 end;
  154.  
  155. fun input (is, n) = inputc is n;
  156.  
  157. fun lookahead (is as ref {closed, ic}) =
  158.   if closed then "" else
  159.   let val pos = caml_pos_in ic in
  160.     case try_input_char_ ic of
  161.         NONE   => ""
  162.       | SOME c =>
  163.           let val () = caml_seek_in ic pos
  164.               val s = create_string_ 1
  165.           in set_nth_char_ s 0 c; s end
  166.   end;
  167.  
  168. fun close_in (is as ref {closed, ic}) =
  169.   if closed then () else
  170.     (caml_close_in ic;
  171.      is := { closed=true, ic=ic };
  172.      ());
  173.  
  174. fun end_of_stream is = (lookahead is = "");
  175.  
  176. fun open_out s =
  177.   ref {closed=false, oc=caml_open_out s}
  178.   handle exn as SysErr _ => raiseIo "open_out" s exn;
  179.  
  180. fun open_out_bin s =
  181.   ref {closed=false, oc=caml_open_out_bin s}
  182.   handle exn as SysErr _ => raiseIo "open_out_bin" s exn;
  183.  
  184. fun outputc (os as ref {closed, oc}) s =
  185.   if closed then
  186.     raiseClosed "outputc" "" 
  187.   else
  188.     (caml_output_string oc s;
  189.      if os = std_err then caml_flush oc else ());
  190.  
  191. fun output (os, s) = outputc os s;
  192.  
  193. fun close_out (os as ref {closed, oc}) =
  194.   if closed then () else
  195.     (caml_close_out oc; os := {closed = true, oc=oc}; ());
  196.  
  197. fun flush_out (os as ref {closed, oc}) =
  198.   if closed then
  199.     raiseClosed "flush_out" ""
  200.   else
  201.     caml_flush oc;
  202.  
  203. fun input_line (is as ref {closed, ic}) =
  204.   if closed then "" else
  205.   let val max = ref 127
  206.       val tmp = ref (create_string_ (!max))
  207.       fun realloc () =
  208.       let val newmax = 2 * !max
  209.           val newtmp = create_string_ newmax
  210.       in 
  211.           blit_string_ (!tmp) 0 newtmp 0 (!max);
  212.           max := newmax;
  213.           tmp := newtmp
  214.       end
  215.       fun h len =
  216.       case try_input_char_ ic of
  217.           NONE   => sub_string_ (!tmp) 0 len
  218.         | SOME c => (if len >= !max then realloc () else ();
  219.              set_nth_char_ (!tmp) len c;
  220.              if c = #"\n" then sub_string_ (!tmp) 0 (len+1) 
  221.                           else h (len+1))
  222.   in h 0 end;
  223.  
  224. fun can_inputc (is as ref {closed, ic}) n =
  225.   if n<0 then false else
  226.   if closed then n=0 else
  227.   let
  228.     val pos = caml_pos_in ic
  229.     val buff = create_string_ n
  230.     val n' = fast_input ic buff 0 n
  231.   in caml_seek_in ic pos; n' = n end;
  232.  
  233. fun can_input (is, n) = can_inputc is n;
  234.  
  235. fun open_append s =
  236.   ref { closed=false,
  237.         oc=open_out_gen [O_WRONLY, O_APPEND, O_CREAT, O_TEXT]
  238.                         (s_irall + s_iwall) s }
  239.   handle exn as SysErr _ => raiseIo "open_append" s exn;
  240.  
  241. prim_val sys_exit : int -> 'a = 1 "sys_exit";
  242.  
  243. fun exit n =
  244.   (flush_out std_out; flush_out std_err; sys_exit n)
  245. ;
  246.  
  247. fun print s = (outputc std_out s; flush_out std_out);
  248.